package com.boulderai.mcp.example;

import com.boulderai.mcp.client.McpClient;
import com.boulderai.mcp.client.McpClientFactory;
import com.boulderai.mcp.model.McpMessage;
import com.boulderai.mcp.model.Resource;
import com.boulderai.mcp.model.Tool;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Scanner;
import java.util.concurrent.CompletableFuture;

/**
 * MCP客户端使用示例
 */
public class McpClientExample {
    
    private static final Logger logger = LoggerFactory.getLogger(McpClientExample.class);
    private static final ObjectMapper objectMapper = new ObjectMapper();
    
    public static void main(String[] args) {
        if (args.length < 1) {
            System.out.println("Usage: java McpClientExample <server-uri>");
            System.out.println("Example: java McpClientExample ws://localhost:8080/mcp");
            return;
        }
        
        String serverUri = args[0];
        McpClientExample example = new McpClientExample();
        example.run(serverUri);
    }
    
    public void run(String serverUri) {
        McpClient client = McpClientFactory.createClient(serverUri);
        
        // 设置消息处理器
        client.setMessageHandler(new McpClient.McpMessageHandler() {
            @Override
            public void onMessage(McpMessage message) {
                logger.info("Received message: method={}, params={}", 
                           message.getMethod(), message.getParams());
            }
            
            @Override
            public void onError(Throwable error) {
                logger.error("Client error", error);
            }
            
            @Override
            public void onClose(int code, String reason) {
                logger.info("Connection closed: code={}, reason={}", code, reason);
            }
        });
        
        try {
            // 连接到服务器
            System.out.println("Connecting to MCP server: " + serverUri);
            client.connect(serverUri).get();
            System.out.println("Connected successfully!");
            
            // 初始化会话
            JsonNode clientInfo = objectMapper.createObjectNode()
                    .put("name", "Boulder AI MCP Client")
                    .put("version", "1.0.0");
            
            JsonNode initResult = client.initialize(clientInfo).get();
            System.out.println("Initialization result: " + initResult);
            
            // 启动交互式命令行界面
            runInteractiveMode(client);
            
        } catch (Exception e) {
            logger.error("Error running MCP client", e);
        } finally {
            try {
                client.disconnect().get();
                System.out.println("Disconnected from server");
            } catch (Exception e) {
                logger.error("Error disconnecting", e);
            }
        }
    }
    
    private void runInteractiveMode(McpClient client) {
        Scanner scanner = new Scanner(System.in);
        
        System.out.println("\n=== MCP Client Interactive Mode ===");
        System.out.println("Available commands:");
        System.out.println("  list-tools    - List available tools");
        System.out.println("  list-resources - List available resources");
        System.out.println("  call-tool <name> <args> - Call a tool");
        System.out.println("  read-resource <uri> - Read a resource");
        System.out.println("  quit          - Exit the program");
        System.out.println();
        
        while (true) {
            System.out.print("mcp> ");
            String input = scanner.nextLine().trim();
            
            if (input.isEmpty()) {
                continue;
            }
            
            String[] parts = input.split("\\s+", 3);
            String command = parts[0].toLowerCase();
            
            try {
                switch (command) {
                    case "quit":
                    case "exit":
                        return;
                        
                    case "list-tools":
                        handleListTools(client);
                        break;
                        
                    case "list-resources":
                        handleListResources(client);
                        break;
                        
                    case "call-tool":
                        if (parts.length >= 2) {
                            String toolName = parts[1];
                            String argsJson = parts.length > 2 ? parts[2] : "{}";
                            handleCallTool(client, toolName, argsJson);
                        } else {
                            System.out.println("Usage: call-tool <name> [<args-json>]");
                        }
                        break;
                        
                    case "read-resource":
                        if (parts.length >= 2) {
                            String resourceUri = parts[1];
                            handleReadResource(client, resourceUri);
                        } else {
                            System.out.println("Usage: read-resource <uri>");
                        }
                        break;
                        
                    default:
                        System.out.println("Unknown command: " + command);
                        break;
                }
            } catch (Exception e) {
                System.out.println("Error executing command: " + e.getMessage());
                logger.debug("Command execution error", e);
            }
        }
    }
    
    private void handleListTools(McpClient client) throws Exception {
        CompletableFuture<List<Tool>> future = client.listTools();
        List<Tool> tools = future.get();
        
        System.out.println("Available tools:");
        if (tools.isEmpty()) {
            System.out.println("  (no tools available)");
        } else {
            for (Tool tool : tools) {
                System.out.printf("  - %s: %s%n", tool.getName(), tool.getDescription());
            }
        }
    }
    
    private void handleListResources(McpClient client) throws Exception {
        CompletableFuture<List<Resource>> future = client.listResources();
        List<Resource> resources = future.get();
        
        System.out.println("Available resources:");
        if (resources.isEmpty()) {
            System.out.println("  (no resources available)");
        } else {
            for (Resource resource : resources) {
                System.out.printf("  - %s (%s): %s%n", 
                                resource.getName(), resource.getUri(), resource.getDescription());
            }
        }
    }
    
    private void handleCallTool(McpClient client, String toolName, String argsJson) throws Exception {
        JsonNode arguments = objectMapper.readTree(argsJson);
        CompletableFuture<JsonNode> future = client.callTool(toolName, arguments);
        JsonNode result = future.get();
        
        System.out.println("Tool call result:");
        System.out.println(objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(result));
    }
    
    private void handleReadResource(McpClient client, String resourceUri) throws Exception {
        CompletableFuture<JsonNode> future = client.readResource(resourceUri);
        JsonNode result = future.get();
        
        System.out.println("Resource content:");
        System.out.println(objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(result));
    }
}